﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Audio;
using OpenTK.Audio.OpenAL;
using OpenTK.Input;
using System.Drawing;

namespace Watcher.Presentation.Visualization
{
    public class PlotEngine : GameWindow
    {

        static readonly Font TextFont = new Font(FontFamily.GenericSansSerif, 12);
        Bitmap TextBitmap = new Bitmap(512, 512);
        int texture;
        bool mouse_in_window = false;
        bool viewport_changed = true;
        bool refresh_text = true;

        Vector3d[] vertices = new Vector3d[1000];
        List<Vector3d> vert = new List<Vector3d>();
        int zoom = 0;
        double x = 0f;
        double y = 0.0;

        List<Vector3d> vert2 = new List<Vector3d>();
        double x2 = -10.0;
        double y2 = 0.0;

        List<Vector3d> vert3 = new List<Vector3d>();
        double x3 = -10.0;
        double y3 = 0.0;

        List<Vector3d> vert4 = new List<Vector3d>();
        double x4 = -10.0;
        double y4 = 0.0;

        double incr = 0.01;

        public PlotEngine() : base(720, 480, GraphicsMode.Default, "OpenTK Quick Start Sample", GameWindowFlags.Default)
        {
            VSync = VSyncMode.On;
        }
        
        //public override PlotEngine(Graph graph) : base(720, 480, GraphicsMode.Default, "OpenTK Quick Start Sample", GameWindowFlags.Default)
        //{
            
        //}

        //public override PlotEngine(LineGraph graph)
        //    : base(720, 480, GraphicsMode.Default, "OpenTK Quick Start Sample", GameWindowFlags.Default)
        //{

        //}


        /// <summary>Load resources here.</summary>
        /// <param name="e">Not used.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            GL.Enable(EnableCap.DepthTest);
        }

        /// <summary>
        /// Called when your window is resized. Set your viewport here. It is also
        /// a good place to set up your projection matrix (which probably changes
        /// along when the aspect ratio of your window).
        /// </summary>
        /// <param name="e">Not used.</param>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);

            Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref projection);
        }

        /// <summary>
        /// Called when it is time to setup the next frame. Add you game logic here.
        /// </summary>
        /// <param name="e">Contains timing information for framerate independent logic.</param>
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);

            if (Keyboard[Key.Escape])
                Exit();

            if (Keyboard[Key.RControl] && Keyboard[Key.Up])
            {
                zoom += 1;
            }

            if (Keyboard[Key.RControl] && Keyboard[Key.Down])
            {
                zoom -= 1;
            }

        }

        /// <summary>
        /// Called when it is time to render the next frame. Add your rendering code here.
        /// </summary>
        /// <param name="e">Contains timing information.</param>
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            Matrix4 lookat = Matrix4.LookAt(0, 0, 7.5f + zoom, 0, 0, 0, 0, 1, -3);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref lookat);
            GL.Begin(BeginMode.LineStrip);
            y = Math.Sin(x / 2) * 5;
            x = x + incr;
            vert.Add(new Vector3d(x, y, 0));
            foreach (Vector3d vertex in vert)
            {
                GL.Color3(Math.Abs(vertex.Y) / 2, 2.0f - (Math.Abs(vertex.Y) - (Math.Abs(vertex.Y) / 3)), Math.Abs(vertex.Y));
                GL.Vertex3(vertex.X - x, vertex.Y, vertex.Z);
            }
            GL.End();
            GL.Begin(BeginMode.LineStrip);
            y2 = Math.Cos(x * 5) * 2;
            vert2.Add(new Vector3d(x, y2, 0));
            foreach (Vector3d vertex in vert2)
            {
                GL.Color3(Math.Abs(vertex.Y), 2.0f - (Math.Abs(vertex.Y) - (Math.Abs(vertex.Y) / 4)), 0);

                GL.Vertex3(vertex.X - x, vertex.Y, vertex.Z);
            }
            GL.End();
            GL.Begin(BeginMode.LineStrip);
            y3 = Math.Pow(Math.Sin(x), 2) * 2;
            vert3.Add(new Vector3d(x, y3, 0));
            foreach (Vector3d vertex in vert3)
            {
                GL.Color3(0, 2.0f - (Math.Abs(vertex.Y) - (Math.Abs(vertex.Y) / 4)), Math.Abs(vertex.Y));

                GL.Vertex3(vertex.X - x, vertex.Y, vertex.Z);
            }
            GL.End();
            GL.Begin(BeginMode.LineStrip);
            y4 = Math.Pow(Math.E, -0.1 * x) * 5 * Math.Cos(5 * x);
            vert4.Add(new Vector3d(x, y4, 0));
            foreach (Vector3d vertex in vert4)
            {
                GL.Color3(0, 2.0f - (Math.Abs(vertex.Y) - (Math.Abs(vertex.Y) / 4)), Math.Abs(vertex.Y));
                GL.Vertex3(vertex.X - x, vertex.Y, vertex.Z);
            }
            GL.End();
            SwapBuffers();
        }

        static void DrawString(Graphics gfx, string str, int line)
        {
            gfx.DrawString(str, TextFont, Brushes.White, new PointF(0, line * TextFont.Height));
        }


        private void CreateGameWindow()
        {

        }
    }
}
